﻿using static System.Math;

namespace GeoFits
{
    /// <summary>
    /// 几何图形类：直线
    /// </summary>
    public class Line : Geometry
    {
        /// <summary>
        /// 用起始点和终点来确一条直线
        /// </summary>
        /// <param name="beginPt">起始点</param>
        /// <param name="endPt">终点</param>
        public Line(Point beginPt, Point endPt)
        {
            PointOnLine = beginPt;
            Direction = (endPt - beginPt).Normalize();
        }
        /// <summary>
        /// 初始化一条默认直线
        /// </summary>
        /// <remarks>默认直线为X轴</remarks>
        public Line()
        {
            PointOnLine = new Point();//0点
            Direction = new Vector(1, 0, 0);
        }
        /// <summary>
        /// 用起始点和方向向量构造一条直线
        /// </summary>
        /// <param name="beginPt">起始点</param>
        /// <param name="dir">方向向量</param>
        public Line(Point beginPt, Vector dir)
        {
            if (dir.Length == 0.0)
            {
                throw new VectorZeroLengthException();
            }
            PointOnLine = beginPt;
            Direction = dir.Normalize();
        }
        /// <summary>
        /// 点到直线的距离
        /// </summary>
        /// <param name="pt">点</param>
        /// <returns>距离</returns>
        public double DistanceTo(Point pt)
        {
            Vector P = pt - PointOnLine;
            double cos = P.DotProduct(Direction) / (Direction.Length * P.Length);
            double sin = Sqrt(1 - cos * cos);
            return P.Length * sin;
        }
        /// <summary>
        /// 获取直线上离某点最近的点
        /// </summary>
        /// <param name="pt">点</param>
        /// <returns>在直线上与输入点最近的点</returns>
        public Point getNearestPoint(Point pt)
        {
            Vector P = pt - PointOnLine;
            double cos = P.DotProduct(Direction) / (Direction.Length * P.Length);
            double dist = P.Length * cos;
            //double sin = Sqrt(1 - cos * cos);
            return PointOnLine + (dist / Direction.Length) * Direction;
        }
        #region 变量和属性
        private Vector _dir;
        private Point _pt;
        /// <summary>
        /// 设置或获取直线上的一点
        /// </summary>
        /// <value>设置或获取直线上的一点</value>
        public Point PointOnLine
        {
            get
            {
                return _pt;
            }
            set
            {
                _pt = value;
            }
        }
        /// <summary>
        /// 直线的方向向量
        /// </summary>
        /// <value>直线的方向向量</value>
        /// <exception cref="System.Exception">设置方向向量为0向量时抛出异常。</exception>
        public Vector Direction
        {
            get
            {
                return _dir;
            }
            set
            {
                if (value.Length == 0.0)
                {
                    throw new VectorZeroLengthException();
                }
                _dir = value.Normalize();
            }
        }
        ///// <summary>
        ///// 获取起始点的X坐标
        ///// </summary>
        ///// <value>获取起始点的X坐标</value>
        //public double a
        //{
        //    get
        //    {
        //        return this.PointOnLine.X;
        //    }
        //}
        ///// <summary>
        ///// 获取起始点的Y坐标
        ///// </summary>
        ///// <value>获取起始点的Y坐标</value>
        //public double b
        //{
        //    get
        //    {
        //        return this.PointOnLine.Y;
        //    }
        //}
        ///// <summary>
        ///// 获取起始点的Z坐标
        ///// </summary>
        ///// <value>获取起始点的Z坐标</value>
        //public double c
        //{
        //    get
        //    {
        //        return this.PointOnLine.Z;
        //    }
        //}
        ///// <summary>
        ///// 获取方向向量的X坐标
        ///// </summary>
        ///// <value>获取方向向量的X坐标</value>
        //public double m
        //{
        //    get
        //    {
        //        return this.Direction.X;
        //    }
        //}
        ///// <summary>
        ///// 获取方向向量的Y坐标
        ///// </summary>
        ///// <value>获取方向向量的Y坐标</value>
        //public double n
        //{
        //    get
        //    {
        //        return this.Direction.Y;
        //    }
        //}
        ///// <summary>
        ///// 获取方向向量的Z坐标
        ///// </summary>
        ///// <value>获取方向向量的Z坐标</value>
        //public double p
        //{
        //    get
        //    {
        //        return this.Direction.Z;
        //    }
        //}
        #endregion

    }
}
